package com.imchen.cms.cmscore.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.imchen.cms.cmscore.dao.HtmlMapper;
import com.imchen.cms.cmscore.model.Article;
import com.imchen.cms.cmscore.model.Html;
import com.imchen.cms.constant.CMS;
import com.imchen.cms.cmscore.dao.ArticleMapper;
import com.imchen.cms.exception.CmsException;
import com.imchen.cms.utils.FreeMarkerUtil;
import com.imchen.cms.utils.ServiceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileNotFoundException;
import java.util.*;


/**
 * @author imchen
 * @create: 2019-01-11 15:35
 **/
@Service
public class ArticleService implements BaseService<Article> {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${cms.html.path}")
    private String htmlSavePath;

    @Value("${cms.host}")
    private String host;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Autowired
    private ArticleMapper mapper;

    @Autowired
    private HtmlMapper htmlMapper;

    @Autowired
    private HTMLService htmlService;

    @Autowired
    private TemplateService templateService;

    public Article find(int id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public HashMap<String, Integer> add(Article article) throws CmsException {
        String content = article.getContent();
        if (content == null) {
            throw new CmsException("content can not empty", 404);
        }
        int count = mapper.insertSelective(article);
        HashMap<String, Integer> map = new HashMap<>();
        map.put("count", count);
        map.put("id", article.getId());
        logger.debug("insert id is :{}", article.getId());
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    public int addOne(Article article) {
        return mapper.insertSelective(article);
    }

    @Override
    @Transactional(readOnly = true,rollbackFor = Exception.class)
    public Article findById(int id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public int removeById(int id) {
        return 0;
    }

    @Override
    public int update(Article article) {
        return mapper.updateByPrimaryKeySelective(article);

    }

    public int remove(int id) {
        return mapper.deleteByPrimaryKey(id);
    }

    public List<Article> findByPage(int currentIndex, int pageSize) {
        return mapper.selectArticles(currentIndex, pageSize);
    }

    @Override
    public int deleteById(int id) {
        return mapper.deleteByPrimaryKeyLogic(id, CMS.DATA_IS_DELETE);
    }

    public int restoreById(int id) {
        return mapper.deleteByPrimaryKeyLogic(id, CMS.DATA_NOT_DELETE);
    }

    public PageInfo<Article> findByPageHelper(int index, int pageSize) {
        PageHelper.startPage(index, pageSize);
        List<Article> articleList = mapper.selectAllArticles(null);
        return new PageInfo<>(articleList);
    }

    public PageInfo<Article> findByPageHelper(int index, int pageSize, String tags) {
        PageHelper.startPage(index, pageSize);
        List<Article> articleList = mapper.selectAllArticles(tags);
        return new PageInfo<>(articleList);
    }

    @Transactional(rollbackFor = Exception.class )
    public HashMap<String, Integer> addAndDeploy(Article article) throws Exception {

        int count = addOne(article);
        int articleId = article.getId();
        if (count > 0) {
            article.setCreateTime(new Date());
            Html html = null;
            String uuidHtmlFileName = UUID.randomUUID().toString().replace("-", "") + ".html";
//            int templateId = article.getHtml().getTemplateId();
//            String templateName = templateService.findById(templateId).getName();

//            Article record = find(articleId);
//            HashMap<String, Object> dataModel = new HashMap<>();
//            dataModel.put("article", record);
//            boolean result = FreeMarkerUtil.generateHTML(templateName, dataModel, htmlSavePath + "/" + articleId + "/" + uuidHtmlFileName);

            logger.debug("server context-path is:{}", System.getProperty("server.servlet.context-path", contextPath));
            html = deploy(article, uuidHtmlFileName);
            if (html == null) {
                throw new CmsException("generate html failed!", 500);
            }
            return ServiceUtil.toAddMap(1, articleId);
        }
        return ServiceUtil.toAddMap(count, articleId);

    }

    @Transactional(rollbackFor = Exception.class)
    public Html deploy(Article article, String fileName) throws Exception {
        int count = 0;
        Html html = null;
        int articleId = article.getId();
        int templateId = article.getHtml().getTemplateId();

//        外链的不生成html
        if (article.getType() == 3) {
            html = new Html();
            html.setArticleId(articleId);
            html.setTemplateId(1);
            html.setUrl(article.getContent());
            count = htmlService.addOne(html);
        } else {
            String savePath = htmlSavePath + "/" + articleId + "/";
            String uuidHtmlFileName = UUID.randomUUID().toString().replace("-", "") + ".html";
            if (fileName == null) {
                fileName = uuidHtmlFileName;
            }

            HashMap<String, Object> dataModel = new HashMap<>();
            dataModel.put("article", article);
            String templateName = templateService.findById(templateId).getName();
            boolean result = FreeMarkerUtil.generateHTML(templateName, dataModel, savePath + fileName);
            if (result) {
                html = new Html();
                html.setArticleId(articleId);
                html.setTemplateId(1);
                html.setUrl(host + System.getProperty("server.servlet.context-path", contextPath) + "/article/" + articleId + "/" + fileName);
                count = htmlService.addOne(html);
            }else{
                throw new CmsException("HTML生成失败",CMS.EX_HTMLGENERATE_ERROR);
            }
        }
        return count > 0 ? html : null;
    }

    //    HTML file regenerate
    public boolean reDeploy(int articleId, int templateId) {
        boolean result = false;
        Html html = htmlService.findByArticleAndTemplateId(articleId, templateId);
        Article article = findById(articleId);
        HashMap<String, Object> dataModel = new HashMap<>();
        dataModel.put("article", article);
        if (html != null) {
            String url = html.getUrl();
            String htmlName = url.substring(url.lastIndexOf("/"));
            result = FreeMarkerUtil.generateHTML("article.ftl", dataModel, htmlSavePath + "/" + articleId + "/" + htmlName);
        }
        return result;
    }

    public ResponseEntity<Resource> view(int id, String fileName) throws CmsException, FileNotFoundException {
        String filePath = htmlSavePath + "/" + id + "/" + fileName;
        return ServiceUtil.view(filePath);
    }
}